/********************************************************************************
* @file    led_gpio.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-07-02
* @brief   LED灯光，GPIO控制，不实现呼吸效果和亮度调整
* @example

在[business_function.h]中配置LED。 [APP LED]-[Light driven mode]
在[business_gpio.h]中配置LED点亮电平 LS_LED0_LIGHT_LEVEL

#include "ls_syscfg.h"
#include "ls_gpio.h"
#include "bsp_led.h"
#include "app_led.h"
// 初始化led功能
bsp_led_init();
// 初始化APP_LED(创建软定时器)
app_led_init();
// 关闭灯光
app_led_indicate(LED_DRIVEN_GPIO, APP_LED_ID_0, LED_TYPE_OFF, 0, 0);
********************************************************************************/
/* Private Includes ----------------------------------------------------------*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#include "app_led.h"
#include "bsp_led.h"
#include "os_api.h"
#include "log.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
/* Private Macro -------------------------------------------------------------*/
#if LS_APP_LED_GPIO_DRIVEN_MODE
#if LS_LEDN > 0
static void timer_led0_light_control(void const *arg);
#endif

#if LS_LEDN > 1
static void timer_led1_light_control(void const *arg);
#endif

#if LS_LEDN > 2
static void timer_led2_light_control(void const *arg);
#endif

#if LS_LEDN > 3
static void timer_led3_light_control(void const *arg);
#endif

#if LS_LEDN > 4
static void timer_led4_light_control(void const *arg);
#endif

#if LS_LEDN > 5
static void timer_led5_light_control(void const *arg);
#endif

#if LS_LEDN > 6
static void timer_led6_light_control(void const *arg);
#endif

#if LS_LEDN > 7
static void timer_led7_light_control(void const *arg);
#endif
#endif
/* Private Typedef -----------------------------------------------------------*/

// 定义led灯光结构体类型
typedef struct
{
    app_led_id_t     led_id;               // 组号
    app_led_type_t   type;                 // 0--灭灯  1--常亮  2--呼吸  3--快闪
    bool             level_logic;          // 0--低电平亮  1--高电平亮
    char            *timer_id;             // 软定时器id
    uint16_t         period_max;           // 重装载值(最大值)
    uint16_t         cycle_time;           // 定时器轮询时间(灭灯和常亮只执行一次)
    uint16_t         period;               // 重装载值(控制值)
    // 下面不用填写，仅用于临时计算
    uint8_t          temp_dir;             // 用于方向 0--up 1--keep 2--down
    uint16_t         temp_times;           // 用于计次
} app_led_t;

// 定义软定时器，用于实现灯光效果
#if LS_APP_LED_GPIO_DRIVEN_MODE
#if LS_LEDN > 0
app_led_t app_gpio_led0 = {APP_LED_ID_0, LED_TYPE_OFF, LS_LED0_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led0, timer_led0_light_control);

#endif

#if LS_LEDN > 1
app_led_t app_gpio_led1 = {APP_LED_ID_1, LED_TYPE_OFF, LS_LED1_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led1, timer_led1_light_control);
#endif

#if LS_LEDN > 2
app_led_t app_gpio_led2 = {APP_LED_ID_2, LED_TYPE_OFF, LS_LED2_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led2, timer_led2_light_control);
#endif

#if LS_LEDN > 3
app_led_t app_gpio_led3 = {APP_LED_ID_3, LED_TYPE_OFF, LS_LED3_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led3, timer_led3_light_control);
#endif

#if LS_LEDN > 4
app_led_t app_gpio_led4 = {APP_LED_ID_4, LED_TYPE_OFF, LS_LED4_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led4, timer_led4_light_control);
#endif

#if LS_LEDN > 5
app_led_t app_gpio_led5 = {APP_LED_ID_5, LED_TYPE_OFF, LS_LED5_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led5, timer_led5_light_control);
#endif

#if LS_LEDN > 6
app_led_t app_gpio_led6 = {APP_LED_ID_6, LED_TYPE_OFF, LS_LED6_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led6, timer_led6_light_control);
#endif

#if LS_LEDN > 7
app_led_t app_gpio_led7 = {APP_LED_ID_7, LED_TYPE_OFF, LS_LED7_LIGHT_LEVEL, NULL, 1, 0, 0, 1, 0};
os_timer_def(led7, timer_led7_light_control);
#endif
#endif
/* Private Function Prototypes ----------------------------------------------*/
/*********************[灯光类型]对内接口函数************************************/
#if LS_APP_LED_GPIO_DRIVEN_MODE
/**
 * @brief  关闭灯光
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_off(app_led_t *app_led)
{
    bsp_led_off((bsp_led_t)app_led->led_id);
}

/**
 * @brief  灯光常亮
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_light(app_led_t *app_led)
{
    bsp_led_on((bsp_led_t)app_led->led_id);
}

/**
 * @brief  灯光闪烁
 * @note   闪烁频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_twinkle(app_led_t *app_led)
{
    if (app_led->temp_dir == 0)
    {
        bsp_led_on((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_dir == 1)
    {
        bsp_led_off((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 0;
    }
    else
    {
        app_led->temp_dir = 0;
    }
    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}

/**
 * @brief  灯光SOS灯效
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_sos(app_led_t *app_led)
{
    uint16_t time = 0;
    if (app_led->temp_dir == 0)
    {
        bsp_led_on((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 1;
        time = 100;
        goto end;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_times++;
        bsp_led_off((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 0;
        if (app_led->temp_times > 2)
        {
            app_led->temp_times = 0;
            app_led->temp_dir = 2;
        }
        time = 200;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        bsp_led_on((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 3;
        time = 800;
        goto end;
    }
    else if (app_led->temp_dir == 3)
    {
        app_led->temp_times++;
        bsp_led_off((bsp_led_t)app_led->led_id);
        app_led->temp_dir = 2;
        if (app_led->temp_times > 2)
        {
            app_led->temp_times = 0;
            app_led->temp_dir   = 0;
        }
        time = 200;
        goto end;
    }
    else
    {
        app_led->temp_dir = 0;
    }
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/************************************[软定时器][回调函数]灯光操作************************************/
#if LS_LEDN > 0
static void timer_gpio_light_control(app_led_t *app_led)
{
    if (app_led->type == LED_TYPE_OFF)
    {
        led_type_off(app_led);
    }
    else if (app_led->type == LED_TYPE_LIGHT)
    {
        led_type_light(app_led);
    }
    else if (app_led->type == LED_TYPE_TWINKLE)
    {
        led_type_twinkle(app_led);
    }
    else if (app_led->type == LED_TYPE_SOS)
    {
        led_type_sos(app_led);
    }
}
/**
 * @brief  [软定时器回调函数][led0] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led0_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led0);
}
#endif

#if LS_LEDN > 1
/**
 * @brief  [软定时器回调函数][led1] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led1_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led1);
}
#endif

#if LS_LEDN > 2
/**
 * @brief  [软定时器回调函数][led2] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led2_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led2);
}
#endif

#if LS_LEDN > 3
/**
 * @brief  [软定时器回调函数][led3] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led3_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led3);
}
#endif

#if LS_LEDN > 4
/**
 * @brief  [软定时器回调函数][led4] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led4_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led4);
}
#endif

#if LS_LEDN > 5
/**
 * @brief  [软定时器回调函数][led5] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led5_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led5);
}
#endif
#if LS_LEDN > 6
/**
 * @brief  [软定时器回调函数][led6] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led6_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led6);
}
#endif

#if LS_LEDN > 7
/**
 * @brief  [软定时器回调函数][led7] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_led7_light_control(void const *arg)
{
    timer_gpio_light_control(&app_gpio_led7);
}
#endif


/**
  * @brief  通过led_id获取结构体指针
  * @param  led_id 灯光id号
  * @return NULL--无效  其他则有效值
  */
static app_led_t *get_app_led(app_led_id_t led_id)
{
    if (led_id == APP_LED_ID_0)
    {
#if LS_LEDN > 0
        return &app_gpio_led0;
#else
        return NULL;
#endif
    }
#if LS_LEDN > 1
    else if (led_id == APP_LED_ID_1)
    {
        return &app_gpio_led1;
    }
#endif
#if LS_LEDN > 2
    else if (led_id == APP_LED_ID_2)
    {
        return &app_gpio_led2;
    }
#endif
#if LS_LEDN > 3
    else if (led_id == APP_LED_ID_3)
    {
        return &app_gpio_led3;
    }
#endif
#if LS_LEDN > 4
    else if (led_id == APP_LED_ID_4)
    {
        return &app_gpio_led4;
    }
#endif
#if LS_LEDN > 5
    else if (led_id == APP_LED_ID_5)
    {
        return &app_gpio_led5;
    }
#endif
#if LS_LEDN > 6
    else if (led_id == APP_LED_ID_6)
    {
        return &app_gpio_led6;
    }
#endif
#if LS_LEDN > 7
    else if (led_id == APP_LED_ID_7)
    {
        return &app_gpio_led7;
    }
#endif
    return NULL;
}

/* Public Function Prototypes -----------------------------------------------*/
/**
 * @brief  [app层][GPIO相关初始化] 定义软定时器和参数设置
 */
void led_gpio_init(void)
{
#if LS_LEDN > 0
    // 用于初始化时接收返回值
    uint32_t timer_led_ret;
    app_gpio_led0.timer_id = (char *)os_timer_create(os_timer(led0), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 1
    app_gpio_led1.timer_id = (char *)os_timer_create(os_timer(led1), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 2
    app_gpio_led2.timer_id = (char *)os_timer_create(os_timer(led2), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 3
    app_gpio_led3.timer_id = (char *)os_timer_create(os_timer(led3), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 4
    app_gpio_led4.timer_id = (char *)os_timer_create(os_timer(led4), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 5
    app_gpio_led5.timer_id = (char *)os_timer_create(os_timer(led5), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 6
    app_gpio_led6.timer_id = (char *)os_timer_create(os_timer(led6), OS_TIMER_ONCE, &timer_led_ret);
#endif
#if LS_LEDN > 7
    app_gpio_led7.timer_id = (char *)os_timer_create(os_timer(led7), OS_TIMER_ONCE, &timer_led_ret);
#endif
}

/**
 * @brief  得到当前组号的灯光模式
 * @param  led_id: led组号
 * @retval 当前组号的灯光模式
 */
app_led_type_t app_led_gpio_get_current_type(app_led_id_t led_id)
{
    app_led_t *app_led = get_app_led(led_id);
    return app_led->type;
}

/**
  * @brief  LED_GPIO 操作
  * @param  led_id led组号
  * @param  type 灯光类型
  * @param  cycle_time 灯光周期(ms) 定时器轮询时间(灭灯和常亮只执行一次)
  * @param  period 重装载值(控制值)
  * @return 0--false 1--true
  */
bool app_led_gpio_ioctl(app_led_id_t led_id, app_led_type_t type, uint16_t cycle_time, uint16_t period)
{
    app_led_t *led_info = NULL;

    led_info = get_app_led(led_id);
    if (led_info == NULL)
    {
        return false;
    }

    led_info->temp_dir    = 0;
    led_info->temp_times  = 0;
    led_info->cycle_time  = cycle_time;
    led_info->period      = period;
    led_info->type        = type;

    os_timer_start((os_timer_id)(led_info->timer_id), 1);
    return true;
}
#endif
